# ~*~ coding: utf-8 ~*~
from flask import request, views, render_template, jsonify
from werkzeug.datastructures import CombinedMultiDict

from apps.common.utils import fill_date_to_timestamp, timestamp_obj_to_str
from apps.common.mixin import CompatibleWithSelect2Mixin
from apps.common import response
from apps.extensions import db
from apps.perms.mixin import PermissionRequiredMixin, LoginRequiredMixin
from ..models import SystemUser
from ..forms import SystemUserCreateUpdateForm


__all__ = [
    'SystemUserListAPI', 'SystemUserListView', 'SystemUserCreateView',
    'SystemUserUpdateView', 'SystemUserDeleteView'
]


class SystemUserListAPI(CompatibleWithSelect2Mixin, PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-systemuser-list'

    def get(self):
        create_time = request.args.get('create_time')
        start_time = end_time = None
        if create_time:
            start_time = fill_date_to_timestamp('start', create_time.split('~')[0])
            end_time = fill_date_to_timestamp('end', create_time.split('~')[1])

        filter_conditions = {
            'and': [
                ('create_time', 'gte', start_time),
                ('create_time', 'lte', end_time),
            ],
            'or': [
                ('name', 'like', request.args.get('search')),
            ],
        }

        # 排序
        sort = request.args.get('sort') or 'create_time'
        order = request.args.get('order') or 'desc'
        order_by_list = [(sort, order), ]

        # 分页
        offset = request.args.get('offset') or 0
        limit = request.args.get('limit') or 12

        # Compatible with select2
        if request.values.get('type') == 'select2':
            filter_conditions, order_by_list, offset, limit = self.select2_queryset()

        system_users, count = SystemUser.get_queryset(filter_conditions=filter_conditions,
                                                      order_by_list=order_by_list,
                                                      offset=offset, limit=limit)
        # 获取关联资产的数量
        results = list()
        for system_user in system_users:
            results.append({
                'id': system_user.id,
                'name': system_user.name,
                'username': system_user.username,
                'login_mode': system_user.login_mode_display,
                'priority': system_user.priority,
                'auto_push': system_user.auto_push,
                'sudo': system_user.sudo,
                'shell': system_user.shell,
                'asset_count': 0,
                'create_time': timestamp_obj_to_str(system_user.create_time),
            })

        resp = {
            "data": {
                "rows": results,
                "total": count
            }
        }
        return jsonify(resp)


class SystemUserListView(PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-systemuser-list'

    def get(self):
        return render_template('assets/systemuser_list.html')


class SystemUserUpdateView(PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-systemuser-update'

    def get(self, pk):
        instance = db.session.query(SystemUser).get(pk)
        content = {
            'id': instance.id,
            'name': instance.name,
            'username': instance.username,
            'password': instance.password or '',
            'login_mode': instance.login_mode,
            'priority': instance.priority,
            'auto_push': instance.auto_push,
            'private_key': instance.private_key or '',
            'sudo': instance.sudo,
            'shell': instance.shell
        }
        return render_template('assets/systemuser_update.html', **content)

    def post(self, pk):
        form = SystemUserCreateUpdateForm(CombinedMultiDict([request.form, request.files]))
        instance = db.session.query(SystemUser).get(pk)
        if form.validate():
            _clean_data = form.data
            if instance.name != _clean_data.get('name'):
                if db.session.query(SystemUser).filter_by(name=_clean_data.get('name')).count():
                    return response.params_error({
                        'field': 'name',
                        'message': '系统用户名称不能重复'
                    })

            login_mode = _clean_data.get('login_mode')
            private_key = _clean_data.get('private_key')
            # 自动登录
            if login_mode == SystemUser.LOGIN_AUTO:
                # 自动生成秘钥 (更新是用户不能选择自动生成秘钥)
                public_key = instance.public_key
                if private_key and private_key != instance.private_key:
                    private_key, public_key = form.gen_keys()
                password = _clean_data.get('password')
            else:
                password, private_key, public_key = None, None, None

            instance.name = _clean_data.get('name')
            instance.username = _clean_data.get('username')
            instance.login_mode = login_mode
            instance.priority = _clean_data.get('priority')
            instance.auto_push = _clean_data.get('auto_push')
            instance.sudo = _clean_data.get('sudo')
            instance.shell = _clean_data.get('shell')
            if private_key and not password:
                instance.set_auth(password=None, private_key=private_key, public_key=public_key)
            if not private_key and password:
                instance.set_auth(password=password, private_key=None, public_key=None)
            if private_key and password:
                instance.set_auth(password=password, private_key=private_key, public_key=public_key)
            if not private_key and not password:
                instance.set_auth(password=password, private_key=private_key, public_key=public_key)
            db.session.commit()
            return response.success()
        else:
            return response.params_error(form.get_error())


class SystemUserCreateView(PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-systemuser-create'

    def get(self):
        return render_template('assets/systemuser_create.html')

    def post(self):
        form = SystemUserCreateUpdateForm(CombinedMultiDict([request.form, request.files]))
        if form.validate():
            _clean_data = form.data
            if db.session.query(SystemUser).filter_by(name=_clean_data.get('name')).count():
                return response.params_error({
                    'field': 'name',
                    'message': '系统用户名称不能重复'
                })
            username = _clean_data.get('username')
            login_mode = _clean_data.get('login_mode')
            auto_generate_key = _clean_data.get('auto_generate_key')

            # 自动登录
            if login_mode == SystemUser.LOGIN_AUTO:
                # 自动生成秘钥
                if auto_generate_key:
                    password, private_key, public_key = SystemUser.gen_auth(username)
                else:
                    private_key, public_key = form.gen_keys()
                    password = _clean_data.get('password') or None
            else:
                password, private_key, public_key = None, None, None

            system_user = SystemUser()
            system_user.name = _clean_data.get('name')
            system_user.username = username
            system_user.login_mode = login_mode
            system_user.priority = _clean_data.get('priority')
            system_user.auto_push = _clean_data.get('auto_push')
            system_user.sudo = _clean_data.get('sudo')
            system_user.shell = _clean_data.get('shell')
            system_user.set_auth(password=password, private_key=private_key, public_key=public_key)
            db.session.add(system_user)
            db.session.commit()
            return response.success()
        else:
            return response.params_error(form.get_error())


class SystemUserDeleteView(PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-systemuser-delete'

    def post(self, pk):
        instance = db.session.query(SystemUser).get(pk)
        instance.delete()
        return response.success()

